package com.sinopec.basemodule.base.baseImpl

import com.sinopec.basemodule.base.BasePresenter
import com.sinopec.basemodule.base.BaseView
import com.sinopec.basemodule.http.CommonObserver
import com.sinopec.basemodule.http.ExceptionEngine
import com.sinopec.basemodule.http.api.HttpResult
import io.reactivex.Observable

open class BasePImpl<T : BaseView>(view: T) : BasePresenterImpl<T>(view) {

    fun <T> Observable<HttpResult<T>>.sub(observer: CommonObserver<T>) {
        toSubscribe(this, observer)
    }

    inline fun <T> Observable<HttpResult<T>>.requestWithScope(
        scope: DSLCommonObserverScope<T>.() -> Unit
    )=sub(scope(scope))

    /**
     * create by lwj
     * commonObserver
     * ===============================================================================
     */
    protected fun obtainContext() = mView.context

    fun <T> observer(block: (t: T) -> Unit) = observer<T>({
        mView.showMessage(it?.message ?: "")
    }, block)

    fun <T> observer(
        onErrorBlock: ((ExceptionEngine.ResponseThrowable?) -> Unit)?,
        block: (t: T) -> Unit,
        cacheKey: String? = null,
        isShowProgress: Boolean = true
    ): CommonObserver<T> {
        return object : CommonObserver<T>(
            cacheKey,
            obtainContext(),
            isShowProgress
        ) {
            override fun onNext(t: T) {

                try {
                    block(t)
                } catch (e: Exception) {
                    onError(e)
                }

            }

            override fun onError(t: ExceptionEngine.ResponseThrowable?) {
                onErrorBlock?.invoke(t)
            }
        }
    }


    private var childPresenter: ArrayList<BasePresenter>? = null

//    fun <T : BaseView, P : BasePImpl<T>> getByType(clazz:Class<P>):P?{
//        return childPresenter?.filterIsInstance(clazz)?.getOrNull(0)
//    }

    /**
     * create by lwj
     * only invoke in init
     */
    fun appendChildPresenter(presenter: BasePresenter) {
        if (childPresenter == null) {
            childPresenter = ArrayList()
        }
        childPresenter?.add(presenter)
    }

    override fun start() {
        super.start()
        childPresenter?.forEach {
            it.start()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        childPresenter?.forEach {
            it.onDestroy()
        }
    }


    /**
     * create by lwj
     * scope
     */
    inline fun <T> scope(block: DSLCommonObserverScope<T>.() -> Unit): CommonObserver<T> {
        val scope = DSLCommonObserverScope<T>()
        scope.block()

        val successBlock = scope._onSuccess
        checkNotNull(successBlock) {
            "onSuccess block没写"
        }
        return observer(
            scope._onErrorBlock ?: {
                mView.showMessage(it?.message ?: "")
            },
            successBlock,
            scope.cacheKey,
            scope.isShowProgress
        )
    }
}

/**
 * create by lwj at
 * 提供契约相加
 */
operator fun <T : BaseView, P : BasePImpl<T>> P.plus(presenter: BasePresenter): P {
    appendChildPresenter(presenter)
    return this
}

///**
// * create by lwj
// * 提供从中获取的手段
// * 你也可以把 presenter 作为本地变量取出
// */
//inline fun <T : BaseView,reified P : BasePImpl<T>> P.get(clazz: Class<out BasePImpl<BaseView>>): BasePImpl<BaseView>? {
//    return getByType(clazz)
//}

/**
 * create by lwj
 * 添加一个dsl支持
 */
class DSLCommonObserverScope<T> {
    var _onErrorBlock: ((ExceptionEngine.ResponseThrowable?) -> Unit)? = null
    var _onSuccess: (((t: T) -> Unit))? = null
    var cacheKey: String? = null
    var isShowProgress: Boolean = true

    fun onSuccess(call: (T) -> Unit) {
        _onSuccess = call
    }

    fun onError(call: (ExceptionEngine.ResponseThrowable?) -> Unit) {
        _onErrorBlock = call
    }

}